package com.capgemini.teamtwo.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.capgemini.teamtwo.common.BusinessException;
import com.capgemini.teamtwo.common.ExceptionEnum;
import com.capgemini.teamtwo.entity.User;
import com.capgemini.teamtwo.entity.UserLogin;
import com.capgemini.teamtwo.entity.UserEntity;
import com.capgemini.teamtwo.entity.vo.RegVO;
import com.capgemini.teamtwo.mapper.UserAccountMapper;
import com.capgemini.teamtwo.mapper.UserMapper;
import com.capgemini.teamtwo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    UserMapper userMapper;

    @Autowired
    UserAccountMapper userAccountMapper;


    @Override
    public UserLogin login(UserLogin userLogin) {
        // 判断参数是否为空
        if (userLogin == null) {
            throw new BusinessException(ExceptionEnum.PARAMETER_EMPTY);
        }
        UserEntity result = userMapper.findUserByUsername(userLogin.getUsername());
        if (result == null) {
            throw new BusinessException(ExceptionEnum.NOTFOUND_USER_ACCOUNT);
        }
        //检测用户的密码是否匹配
        // 1.先获取到数据库中的加密之后的密码
        String oldPassword = result.getPassword();
        String salt = result.getSalt();
        // 2.2 将用户的密码按照相同的md5算法的规则进行加密
        String newMd5Password = getMD5Password(userLogin.getPassword(), salt);
        // 3. 将密码进行比较
        if (!newMd5Password.equals(oldPassword)) {
            throw new BusinessException(ExceptionEnum.NOTMATCH_USER_PASSWORD);
        }

        UserLogin user = new UserLogin();
        user.setId(result.getId());
        user.setUsername(result.getUsername());
        //将当前的用户数据返回,返回的数据是为了辅助其他页面做数据展示使用
        return user;
    }

    @Override
    public void userReg(RegVO regVO) {

        // 1.参数及数据校验
        this.checkInfo(regVO);

        // 2.将密码和盐值作为一个整体进行加密处理,忽略原有密码强度提升了数据的安全性
        String salt = UUID.randomUUID().toString().toUpperCase();
        String md5Password = getMD5Password(regVO.getPassword(), salt);

        UserEntity user = new UserEntity();
        user.setUsername(regVO.getUsername());
        user.setPassword(md5Password);
        user.setSalt(salt);
        user.setRealname(regVO.getName());
        user.setUserJob(regVO.getPosition());
        userAccountMapper.insert(user);
       // userMapper.reg(user);

    }

    /**
     *  定义一个md5密码加密算法
     *  密码加密处理的实现：MD5算法的形式
     *  串 + password + 串） -----整体md5算法进行加密，连续加载三次
     *  串通常成为盐值 盐值 + password + 盐值  ---盐值就是一个随机的字符串
     *  获取盐值(随机生成一个盐值)
     * @param password
     * @param salt
     * @return
     */
    private String getMD5Password(String password, String salt) {
        for (int i = 0; i < 3; i++) {
            //md5加密算法方法的调用(进行三次加密)
            password = DigestUtils.md5DigestAsHex((salt + password + salt).getBytes()).toUpperCase();
        }
        // 返回加密之后的密码
        return password;
    }

    /**
     * 验证必填项
     * @param regVO 入参
     */
    private void checkInfo(RegVO regVO) {

        /**
         * 必填项校验
         */
        // 验证用户名是否为空
        if (StringUtils.isBlank(regVO.getUsername())){
            throw new BusinessException(ExceptionEnum.USERNAME_IS_NOT_NULL);
        }

        // 验证密码是否为空
        if (StringUtils.isBlank((regVO.getPassword()))){
            throw new BusinessException(ExceptionEnum.PASSWORD_IS_NOT_NULL);
        }

        /**
         * 数据校验
         */
        // 验证账户是否存在，重复提示账户已存在
        String username = userMapper.checkUsername(regVO.getUsername());
        if (StringUtils.isNotBlank(username)) {
            throw new BusinessException(ExceptionEnum.DUPLICATE_USER_ACCOUNT);
        }
        // 密码两次输入不一致提醒
        if (!regVO.getPassword().equals(regVO.getConfirmPassword())) {
            throw new BusinessException(ExceptionEnum.PASSWORD_IS_NOT_EQUALS);
        }

        // 验证密码必须有字母、数字、特殊符号，长度在6-16位
        String pattern = "^(?=.*\\d)((?=.*[a-z])|(?=.*[A-Z])).{6,16}$";

        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(regVO.getPassword());
        boolean matches = m.matches();
        if (!matches) {
            throw new BusinessException(ExceptionEnum.PASSWORD_STRONG);
        }
    }


}
